/********************************************************************************
 ***                                                                          *** 
 ********************************************************************************
 *                                                                              * 
 *           Prject Name : MEMORIA                                              * 
 *                                                                              * 
 *             File Name : editableCard.cpp                                     * 
 *                                                                              * 
 *            Programmer : LBW                                                  * 
 *                                                                              * 
 *            Start Date : 2020/12/26                                           * 
 *                                                                              * 
 *           Last Update : 2020/12/26  [LBW]                                    * 
 *                                                                              * 
 *------------------------------------------------------------------------------*
 * Functions:                                                                   * 
 *   EditableCard::EditableCard -- 构造用于编辑的卡片                           * 
 *   EditableCard::wordCheck -- 检测answer行中选中的文本是否能制作成Nail        * 
 *   EditableCard::reArray -- 重新排列单词顺序                                  * 
 *   EditableCard::showNails -- 刷新WordLine行                                  * 
 *   EditableCard::returnPressed -- 在answer文本行按下回车触发的事件            * 
 *   EditableCard::nailPressed -- 点击Nail快速删除该Nail                        * 
 *   EditableCard::textChanged -- answer文本行的文本变化触发的事件              * 
 *   EditableCard::getId -- 查询卡片在整个卡片集中所处的位置                    * 
 *   EditableCard::setId -- 设置卡片在整个卡片集中所处的位置                    * 
 *   EditableCard::getHeading -- 查询heading文本行当前的文本                    * 
 *   EditableCard::getSentence -- 查询sentence文本行当前的文本                  * 
 *   EditableCard::getAnswer -- 查询answer文本行当前的文本                      * 
 *   EditableCard::getInterference -- 查询interference文本行当前的文本          * 
 *   EditableCard::getWordPos -- 查询当先Nails在answer文本中的位置和长度信息    * 
 *   EditableCard::paintEvent -- Qt中改变部件样式需要定义的事件                 * 
 *   EditableCard::mousePressEvent -- 鼠标点击部件所触发的事件                  * 
 *==============================================================================*/

#include <QtWidgets>
#include <QVector>

#include "parameter.h"
#include "editableCard.h"
#include "nail.h"
#include "wordline.h"

/**********************************************************************************
 * EditableCard::EditableCard -- 构造用于编辑的卡片                               *
 *                                                                                *
 * INPUT: cardId -- 卡片在整个卡片集中所处的位置                                  *
 *        strHeading -- 小标题                                                    *
 *        strSentence -- 翻译好的的母语句子                                       *
 *        strAnswer -- 需要记忆的外语句子                                         *
 *        strWordPos -- 需要记忆的单词所在的位置和长度信息                        *
 *        strInterference -- 干扰词                                               *
 *        parent -- EditableCard的父对象                                          *
 *                                                                                *
 * OUTPUT: none                                                                   *
 *                                                                                *
 * WARNINGS: none                                                                 *
 *                                                                                *
 * HISTORY:                                                                       *
 *   2020/12/26 LBW : Created.                                                    *
 *================================================================================*/
EditableCard::EditableCard(int cardId,QString strHeading,QString strSentence,QString strAnswer,QString strWordPos,QString strInterference,QWidget *parent):QWidget(parent)
{
	id = cardId;	
	answerRemain = strAnswer;
	strToWrite = strWordPos;

	//现有的strWordPos要写入vWordPos和VWordLength
	if(strWordPos != "" && strWordPos.indexOf(",") > 0){
		QStringList wordList = strWordPos.split(";");
		vWordPos.resize(wordList.size());
		vWordLength.resize(wordList.size());
		vWord.resize(wordList.size());

		QString temp;
		for(int i=0;i<wordList.size();i++){
			temp = wordList.at(i);
			QStringList list = temp.split(",");
			vWordPos[i] = list.at(0).toInt();
			vWordLength[i] = list.at(1).toInt();
			vWord[i] = answerRemain.mid(vWordPos[i],vWordLength[i]);
		}
		wordline = new WordLine(answerRemain,vWordPos,vWordLength,"",false,this);
		//在WordLine中创建的Nail的press事件要连接出来
		for(int i=0;i<vWordPos.size();i++){
			connect(wordline->nailAt(i),SIGNAL(nailPressed(int)),this,SLOT(nailPressed(int)));
		}
	}else{
		wordline = new WordLine("",vWordPos,vWordLength,"",false,this);
	}
	mainLayout = new QVBoxLayout;
	mainLayout->setAlignment(Qt::AlignTop);

	QHBoxLayout *headingLayout = new QHBoxLayout;
	headingLayout->setAlignment(Qt::AlignLeft);
	QLabel *headingLabel = new QLabel("Heading:",this);
	heading = new QLineEdit(strHeading,this);
	headingLayout->addWidget(headingLabel);
	headingLayout->addWidget(heading);
	mainLayout->addLayout(headingLayout);

	QHBoxLayout *sentenceLayout = new QHBoxLayout;
	sentenceLayout->setAlignment(Qt::AlignLeft);
	QLabel *sentenceLabel = new QLabel("Translation:",this);
	sentence = new QLineEdit(strSentence,this);
	sentenceLayout->addWidget(sentenceLabel);
	sentenceLayout->addWidget(sentence);
	mainLayout->addLayout(sentenceLayout);

	QHBoxLayout *answerLayout = new QHBoxLayout;
	answerLayout->setAlignment(Qt::AlignLeft);
	QLabel *answerLabel = new QLabel("Original:");
	answer = new QLineEdit(strAnswer,this);
	answerLayout->addWidget(answerLabel);
	answerLayout->addWidget(answer);
	connect(answer,SIGNAL(returnPressed()),this,SLOT(returnPressed()));
	connect(answer,SIGNAL(textChanged(const QString &)),this,SLOT(textChanged(const QString &)));
	mainLayout->addLayout(answerLayout);

	QHBoxLayout *interferenceLayout = new QHBoxLayout;
	interferenceLayout->setAlignment(Qt::AlignLeft);
	QLabel *interferenceLabel = new QLabel("Interference:",this);
	interference = new QLineEdit(strInterference,this);
	interferenceLayout->addWidget(interferenceLabel);
	interferenceLayout->addWidget(interference);
	mainLayout->addLayout(interferenceLayout);

	wordScrollArea = new QScrollArea(this);
	wordScrollArea->setFixedHeight(WORDFIXEDHEIGHT);
	wordScrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
	wordScrollArea->setWidgetResizable(true);
	wordScrollArea->setWidget(wordline);
	mainLayout->addWidget(wordScrollArea);

	setVisible(false);
	setStyleSheet(QString(".EditableCard{background:transparent;border:1px solid gray}"));
	setLayout(mainLayout);
	setFixedHeight(CARDFIXEDHEIGHT);
}

/**********************************************************************************
 * EditableCard::wordCheck -- 检测answer行中选中的文本是否能制作成Nail            *
 *                                                                                *
 *   制作新Nail的条件:Nail数量不能达到上限                                        *
 *                    选中的文本不能和现有Nails有重合的地方                       *
 *                                                                                *
 * INPUT: cardId -- 卡片在整个卡片集中所处的位置                                  *
 *                                                                                *
 * OUTPUT: none                                                                   *
 *                                                                                *
 * WARNINGS: none                                                                 *
 *                                                                                *
 * HISTORY:                                                                       *
 *   2020/12/26 LBW : Created.                                                    *
 *================================================================================*/
bool EditableCard::wordCheck(){
	if(vWordPos.size() >= MAXNAIL){
		qDebug() << "Words reach max amount!";
		return false;
	}
	int wordLeft = answer->selectionStart();
	int wordRight = answer->selectionStart() + answer->selectedText().size();
	if(vWordPos.size() > 0){
		for(int i=0;i<vWordPos.size();i++){
			if(vWordPos[i] <= wordLeft && wordLeft < vWordPos[i]+vWordLength[i])
				return false;
			if(vWordPos[i] < wordRight && wordRight <= vWordPos[i]+vWordLength[i])
				return false;
			if(wordLeft < vWordPos[i] && vWordPos[i]+vWordLength[i] < wordRight)
				return false;
		}
	}
		return true;
}

/**********************************************************************************
 * EditableCard::reArray -- 重新排列单词顺序                                      *
 *                                                                                *
 *   制作了新的Nail之后vWordPos[],vWordLength[]和vWord[]中的数据都要重排顺序      *
 *   以保证写入数据库的strWordPos数据是正确的                                     *
 *                                                                                *
 * INPUT: none                                                                    *
 *                                                                                *
 * OUTPUT: none                                                                   *
 *                                                                                *
 * WARNINGS: none                                                                 *
 *                                                                                *
 * HISTORY:                                                                       *
 *   2020/12/26 LBW : Created.                                                    *
 *================================================================================*/
void EditableCard::reArray(){
	int temp;
	QString strTemp;
	for(int i=0;i<vWordPos.size();i++){
		for(int j=0;j<vWordPos.size();j++){
			if(vWordPos[i] < vWordPos[j]){
				temp = vWordPos[i];
				vWordPos[i] = vWordPos[j];
				vWordPos[j] = temp;
	
				temp = vWordLength[i];
				vWordLength[i] = vWordLength[j];
				vWordLength[j] = temp;		
				
				strTemp = vWord[i];
				vWord[i] = vWord[j];
				vWord[j] = strTemp;
			}
		}
	}
}

/**********************************************************************************
 * EditableCard::showNails -- 刷新WordLine行                                      *
 *                                                                                *
 *   制作了新的Nail或者老的Nail遭到破坏都要重新显示WordLine行                     *
 *                                                                                *
 * INPUT: none                                                                    *
 *                                                                                *
 * OUTPUT: none                                                                   *
 *                                                                                *
 * WARNINGS: none                                                                 *
 *                                                                                *
 * HISTORY:                                                                       *
 *   2020/12/26 LBW : Created.                                                    *
 *================================================================================*/
void EditableCard::showNails(){
	//strToWrite是之后要写入数据库的wordPos字符串
	strToWrite = "";
	for(int i=0;i<vWordPos.size();i++){
		strToWrite.append(QString::number(vWordPos[i])).append(",").append(QString::number(vWordLength[i])).append(";");
	}
		strToWrite.remove(strToWrite.size()-1,1);
		qDebug() << strToWrite;	

	//删掉旧的的Nails
	wordline->deleteLater();

	//创建新的Nails
	wordline = new WordLine(answerRemain,vWordPos,vWordLength,"",false,this);
	for(int i=0;i<vWordPos.size();i++)
		connect(wordline->nailAt(i),SIGNAL(nailPressed(int)),this,SLOT(nailPressed(int)));
	wordScrollArea->takeWidget();
	wordScrollArea->setWidget(wordline);
}

/**********************************************************************************
 * EditableCard::returnPressed -- 在answer文本行按下回车触发的事件                *
 *                                                                                *
 *   将answer行选中的文本快速制作成Nail                                           *
 *                                                                                *
 * INPUT: none                                                                    *
 *                                                                                *
 * OUTPUT: none                                                                   *
 *                                                                                *
 * WARNINGS: none                                                                 *
 *                                                                                *
 * HISTORY:                                                                       *
 *   2020/12/26 LBW : Created.                                                    *
 *================================================================================*/
void EditableCard::returnPressed(){
	if(answer->hasSelectedText()){
		if(wordCheck()){
			vWordPos << answer->selectionStart();
			vWordLength << answer->selectedText().size();
			vWord << answer->selectedText();			
			reArray();

			showNails();
		}
	}
}

/**********************************************************************************
 * EditableCard::nailPressed -- 点击Nail快速删除该Nail                            *
 *                                                                                *
 * INPUT: nailId -- 表示第nailId个单词被按下，需要删除                            *
 *                                                                                *
 * OUTPUT: none                                                                   *
 *                                                                                *
 * WARNINGS: none                                                                 *
 *                                                                                *
 * HISTORY:                                                                       *
 *   2020/12/26 LBW : Created.                                                    *
 *================================================================================*/
void EditableCard::nailPressed(int nailId){
	vWordPos.removeAt(nailId);
	vWordLength.removeAt(nailId);		
	vWord.removeAt(nailId);	

	if(vWordPos.size()>0)
		showNails();
	else{
		strToWrite = "";
		showNails();
	}
}

/**********************************************************************************
 * EditableCard::textChanged -- answer文本行的文本变化触发的事件                  *
 *                                                                                *
 *   answer文本行的变化可能导致现有的Nail遭到破坏，所以每次改动answer行的         *
 *   文本都要检测                                                                 *
 *                                                                                *
 * INPUT: text -- answer行当前的文本                                              *
 *                                                                                *
 * OUTPUT: none                                                                   *
 *                                                                                *
 * WARNINGS: none                                                                 *
 *                                                                                *
 * HISTORY:                                                                       *
 *   2020/12/26 LBW : Created.                                                    *
 *================================================================================*/
void EditableCard::textChanged(const QString &text){
	qDebug() << "answerRemain update!";
	answerRemain = text;

	//由更改文本破坏掉的Nail要删掉
	for(int i=0;i<vWordPos.size();i++){
		if(vWord[i] != answerRemain.mid(vWordPos[i],vWordLength[i])){
			vWordPos.removeAt(i);
			vWordLength.removeAt(i);		
			vWord.removeAt(i);	
			i--;
		}
	}	
			if(vWordPos.size()>0)
				showNails();
			else{
				strToWrite = "";
				showNails();
			}
}

/**********************************************************************************
 * EditableCard::getId -- 查询卡片在整个卡片集中所处的位置                        *
 *                                                                                *
 * INPUT: none                                                                    *
 *                                                                                *
 * OUTPUT: id -- 卡片在整个卡片集中所处的位置                                     *
 *                                                                                *
 * WARNINGS: none                                                                 *
 *                                                                                *
 * HISTORY:                                                                       *
 *   2020/12/26 LBW : Created.                                                    *
 *================================================================================*/
int EditableCard::getId() const{
	return id;
}

/**********************************************************************************
 * EditableCard::setId -- 设置卡片在整个卡片集中所处的位置                        *
 *                                                                                *
 * INPUT: intId -- 卡片在整个卡片集中所处的位置                                   *
 *                                                                                *
 * OUTPUT: none                                                                   *
 *                                                                                *
 * WARNINGS: none                                                                 *
 *                                                                                *
 * HISTORY:                                                                       *
 *   2020/12/26 LBW : Created.                                                    *
 *================================================================================*/
void EditableCard::setId(int intId){
	id = intId;
}

/**********************************************************************************
 * EditableCard::getHeading -- 查询heading文本行当前的文本                        *
 *                                                                                *
 * INPUT: none                                                                    *
 *                                                                                *
 * OUTPUT: heading->text() -- heading文本行当前的文本                             *
 *                                                                                *
 * WARNINGS: none                                                                 *
 *                                                                                *
 * HISTORY:                                                                       *
 *   2020/12/26 LBW : Created.                                                    *
 *================================================================================*/
QString EditableCard::getHeading() const{
	return heading->text();
}

/**********************************************************************************
 * EditableCard::getSentence -- 查询sentence文本行当前的文本                      *
 *                                                                                *
 * INPUT: none                                                                    *
 *                                                                                *
 * OUTPUT: sentence->text() -- sentence文本行当前的文本                           *
 *                                                                                *
 * WARNINGS: none                                                                 *
 *                                                                                *
 * HISTORY:                                                                       *
 *   2020/12/26 LBW : Created.                                                    *
 *================================================================================*/
QString EditableCard::getSentence() const{
	return sentence->text();
}

/**********************************************************************************
 * EditableCard::getAnswer -- 查询answer文本行当前的文本                          *
 *                                                                                *
 * INPUT: none                                                                    *
 *                                                                                *
 * OUTPUT: answer->text() -- answer文本行当前的文本                               *
 *                                                                                *
 * WARNINGS: none                                                                 *
 *                                                                                *
 * HISTORY:                                                                       *
 *   2020/12/26 LBW : Created.                                                    *
 *================================================================================*/
QString EditableCard::getAnswer() const{
	return answer->text();
}

/**********************************************************************************
 * EditableCard::getInterference -- 查询interference文本行当前的文本              *
 *                                                                                *
 * INPUT: none                                                                    *
 *                                                                                *
 * OUTPUT: interference->text() -- interference文本行当前的文本                   *
 *                                                                                *
 * WARNINGS: none                                                                 *
 *                                                                                *
 * HISTORY:                                                                       *
 *   2020/12/26 LBW : Created.                                                    *
 *================================================================================*/
QString EditableCard::getInterference() const{
	return interference->text();
}

/**********************************************************************************
 * EditableCard::getWordPos -- 查询当先Nails在answer文本中的位置和长度信息        *
 *                                                                                *
 * INPUT: none                                                                    *
 *                                                                                *
 * OUTPUT: strToWrite -- 即是准备写入数据库的strWordPos信息                       *
 *                                                                                *
 * WARNINGS: none                                                                 *
 *                                                                                *
 * HISTORY:                                                                       *
 *   2020/12/26 LBW : Created.                                                    *
 *================================================================================*/
QString EditableCard::getWordPos() const{
	return strToWrite;
}

/**********************************************************************************
 * EditableCard::paintEvent -- Qt中改变部件样式需要定义的事件                     *
 *                                                                                *
 * INPUT: none                                                                    *
 *                                                                                *
 * OUTPUT: none                                                                   *
 *                                                                                *
 * WARNINGS: none                                                                 *
 *                                                                                *
 * HISTORY:                                                                       *
 *   2020/12/26 LBW : Created.                                                    *
 *================================================================================*/
void EditableCard::paintEvent(QPaintEvent *)
{
	QStyleOption opt;
	opt.init(this);
	QPainter p(this);
	style()->drawPrimitive(QStyle::PE_Widget,&opt,&p,this);
}

/**********************************************************************************
 * EditableCard::mousePressEvent -- 鼠标点击部件所触发的事件                      *
 *                                                                                *
 * INPUT: event -- 发生在部件上的鼠标事件                                         *
 *                                                                                *
 * OUTPUT: none                                                                   *
 *                                                                                *
 * WARNINGS: none                                                                 *
 *                                                                                *
 * HISTORY:                                                                       *
 *   2020/12/26 LBW : Created.                                                    *
 *================================================================================*/
void EditableCard::mousePressEvent(QMouseEvent *event)
{
	if(event->button() == Qt::LeftButton)
		emit cardPressed(id);
}

